package com.p2p.terminal.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.p2p.common.cache.CacheManager;
import com.p2p.common.enums.ResponseEnum;
import com.p2p.common.utils.ParamUtils;
import com.p2p.common.utils.ReflectionUtils;
import com.p2p.common.utils.ResMessage;
import com.p2p.common.utils.StringUtils;
import com.p2p.common.utils.Underline2Camel;
import com.p2p.terminal.dao.IpDao;
import com.p2p.terminal.po.P2pIp;
import com.p2p.terminal.vo.IpCondition;

@Repository
public class IpDaoImpl implements IpDao {

	private static final Logger logger = LoggerFactory.getLogger(IpDaoImpl.class);

	@Resource
	private JdbcTemplate jdbcTemplate;

	@Override
	public ResMessage<P2pIp> selectIpData(IpCondition dataCondition) {
		Long agentId = dataCondition.getAgentId();
		Integer agentLevel = dataCondition.getAgentLevel();
		String cmac = dataCondition.getCmac();
		String outterNetIp = dataCondition.getOutterNetIp();

		String startTime = dataCondition.getStartTime();
		String endTime = dataCondition.getEndTime();

		int timeDiff = startTime.compareTo(endTime);

		if (timeDiff >= 1) {
			startTime = startTime + endTime;
			endTime = startTime.substring(0, startTime.length() - endTime.length())+" 00:00:00";
			startTime = startTime.substring(endTime.length())+" 23:00:00";
		}else{
			startTime=startTime+" 00:00:00";
			endTime=endTime+" 23:00:00";
		}

		Integer showZero = dataCondition.getShowZero();

		Integer pageIndex = dataCondition.getPageIndex();
		Integer pageSize = dataCondition.getPageSize();
		String sortLineName = dataCondition.getSortLineName();
		String orderType = dataCondition.getOrderType();

		String sqlName = Underline2Camel.camel2Underline(sortLineName, true);

		String table1 = "p2p_ip_" + startTime.replaceAll("(\\d{4})-(\\d{2}).+", "$1$2");
		String table2 = "p2p_ip_" + endTime.replaceAll("(\\d{4})-(\\d{2}).+", "$1$2");

		RowMapper<P2pIp> rowMapper = new BeanPropertyRowMapper<>(P2pIp.class);

		String cmacSql = "";
		if ("0".equals(cmac) || StringUtils.isEmpty(cmac)) {
			cmacSql = "  1=1";

		} else {
			cmacSql = "  cmac = " + cmac;
		}

		String outterNetIpSql = "";
		if ("0".equals(outterNetIp) || StringUtils.isEmpty(outterNetIp)) {
			outterNetIpSql = " AND 1=1";

		} else {
			outterNetIpSql = "  AND outernet_ip = " + outterNetIp;
		}

		String showZeroSql = "";
		if (0 == showZero) {
			showZeroSql = " AND terminal_total_count >0";

		} else {
			showZeroSql = " AND 1=1";

		}

		
		String agentSql = "";
		if (0L == agentId) {
			agentSql = " AND 1=1";

		} else {
			HashMap<String, Set<Long>> cache = (HashMap<String, Set<Long>>) CacheManager.getInstance().getCache("agent_message");
			Set<Long> set = cache.get(StringUtils.Long2String(agentId));
			String agentIdsStr = set2String(set, ",");
			agentSql = "  AND agent_id in(" + agentIdsStr + ")";
		}

		String orderSql = "";
		if (StringUtils.isEmpty(sortLineName)) {
			orderSql = " ";

		} else {
			orderSql = "  order by " + sqlName + " " + orderType;
		}

		int index = pageIndex == 1 ? 0 : ((pageIndex - 1) * pageSize);

		List<P2pIp> result = null;
		Integer pageCount = 0;
		if (table1.equals(table2)) {
			String countSql = "SELECT   count(1)  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time BETWEEN ? AND ? ;";
			String dataSql = "SELECT   *  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time BETWEEN ? AND ?  " + orderSql + " limit ?,?";
			pageCount = jdbcTemplate.queryForObject(countSql, Integer.class, new Object[] { startTime, endTime });
			result = jdbcTemplate.query(dataSql, rowMapper, startTime, endTime, index, pageSize);
		} else {
			String countSqlTable1 = "SELECT   count(1)  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql
					+ showZeroSql + agentSql + " and date_time >= ?  ";
			String countSqlTable2 = "SELECT   count(1)  FROM " + table2 + "   WHERE " + cmacSql + outterNetIpSql
					+ showZeroSql + agentSql + " and date_time <= ? ";

			int pageCountTable1 = jdbcTemplate.queryForObject(countSqlTable1, Integer.class,
					new Object[] { startTime});
			int pageCountTable2 = jdbcTemplate.queryForObject(countSqlTable2, Integer.class, new Object[] { endTime});
			pageCount = pageCountTable1 + pageCountTable2;

			String dataSqlTable1 = "SELECT   *  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time >= ? " + orderSql;

			String dataSqlTable2 = "SELECT   *  FROM " + table2 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time <= ? " + orderSql;

			List<P2pIp> resultTable1 = jdbcTemplate.query(dataSqlTable1, rowMapper, startTime);
			List<P2pIp> resultTable2 = jdbcTemplate.query(dataSqlTable2, rowMapper, endTime);

			if (StringUtils.isEmpty(sortLineName)) {
				resultTable1.addAll(resultTable2);
				result = resultTable1;
			} else {
				List<P2pIp> mergeSort = mergeSort(resultTable1, resultTable2, sortLineName, orderType);
				if (mergeSort.size() >= index && mergeSort.size() <= index + pageSize) {
					result = mergeSort.subList(index, mergeSort.size());
				} else if (mergeSort.size() > index + pageSize) {
					result = mergeSort.subList(index, pageSize + index);
				}
			}

		}

		return new ResMessage<>(result, ResponseEnum.SUCCESS.getMsg(), true, pageCount);
	}

	private String set2String(Set list, String division) {
		StringBuilder itmeString = new StringBuilder();
		list.forEach(item -> {
			itmeString.append(item + division);
		});
		itmeString.deleteCharAt(itmeString.length() - 1);
		return itmeString.toString();
	}

	private List<P2pIp> mergeSort(List<P2pIp> list1, List<P2pIp> list2, String name, String order) {
		ArrayList<P2pIp> result = new ArrayList<P2pIp>();
		int list1Size = list1.size();
		int list2Size = list2.size();
		int list1Index = 0;
		int list2Index = 0;

		while (list1Index < list1Size && list2Index < list2Size) {
			P2pIp p2pIp1 = list1.get(list1Index);
			P2pIp p2pIp2 = list2.get(list2Index);
			String fieldValue1 = ReflectionUtils.getFieldValue(p2pIp1, name).toString();
			String fieldValue2 = ReflectionUtils.getFieldValue(p2pIp2, name).toString();

			if ("desc".equals(order)) {
				if (fieldValue1.compareTo(fieldValue2) >= 0) {
					list1Index += 1;
					result.add(p2pIp1);
				} else {
					list2Index += 1;
					result.add(p2pIp2);
				}
			} else {
				if (fieldValue1.compareTo(fieldValue2) <= 0) {
					list1Index += 1;
					result.add(p2pIp1);
				} else {
					list2Index += 1;
					result.add(p2pIp2);
				}
			}

		}

		if (list1Index == list1Size) {
			result.addAll(list2.subList(list2Index, list2Size));
		} else {
			result.addAll(list1.subList(list1Index, list1Size));
		}
		return result;
	}

	@Override
	public List<P2pIp> exportIpData(HttpServletRequest request) {

		String startTime = ParamUtils.getParameter(request, "startTime");
		String endTime = ParamUtils.getParameter(request, "endTime");
		String agentIdStr = ParamUtils.getParameter(request, "agentId", "0");
		long agentId = StringUtils.str2long(agentIdStr);
		int showZero = ParamUtils.getIntParameter(request, "showZero", 0);

		String cmac = ParamUtils.getParameter(request, "cmac", "0");
		String outterNetIp = ParamUtils.getParameter(request, "outterNetIp", "0");

		int timeDiff = startTime.compareTo(endTime);

		if (timeDiff >= 1) {
			startTime = startTime + endTime;
			endTime = startTime.substring(0, startTime.length() - endTime.length())+" 00:00:00";
			startTime = startTime.substring(endTime.length())+" 23:00:00";
		}else{
			startTime=startTime+" 00:00:00";
			endTime=endTime+" 23:00:00";
		}


		String table1 = "p2p_ip_" + startTime.replaceAll("(\\d{4})-(\\d{2}).+", "$1$2");
		String table2 = "p2p_ip_" + endTime.replaceAll("(\\d{4})-(\\d{2}).+", "$1$2");

		RowMapper<P2pIp> rowMapper = new BeanPropertyRowMapper<>(P2pIp.class);

		String cmacSql = "";
		if ("0".equals(cmac) || StringUtils.isEmpty(cmac)) {
			cmacSql = "  1=1";

		} else {
			cmacSql = "  cmac = " + agentId;
		}

		String outterNetIpSql = "";
		if ("0".equals(outterNetIp) || StringUtils.isEmpty(outterNetIp)) {
			outterNetIpSql = " AND 1=1";

		} else {
			outterNetIpSql = "  AND outernet_ip = " + outterNetIp;
		}

		String showZeroSql = "";
		if (0 == showZero) {
			showZeroSql = " AND terminal_total_count >0";

		} else {
			showZeroSql = " AND 1=1";

		}

		
		String agentSql = "";
		if (0L == agentId) {
			agentSql = " AND 1=1";

		} else {
			HashMap<String, Set<Long>> cache = (HashMap<String, Set<Long>>) CacheManager.getInstance().getCache("agent_message");
			Set<Long> set = cache.get(StringUtils.Long2String(agentId));
			String agentIdsStr = set2String(set, ",");
			agentSql = "  AND agent_id in(" + agentIdsStr + ")";
		}

		List<P2pIp> result = null;
		if (table1.equals(table2)) {
			String dataSql = "SELECT   *  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time BETWEEN ? AND ?  ";
			
			result = jdbcTemplate.query(dataSql, rowMapper, startTime, endTime);
		} else {
			

		
	
			String dataSqlTable1 = "SELECT   *  FROM " + table1 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time >= ? ";

			String dataSqlTable2 = "SELECT   *  FROM " + table2 + "   WHERE " + cmacSql + outterNetIpSql + showZeroSql
					+ agentSql + " and date_time <= ? ";

			List<P2pIp> resultTable1 = jdbcTemplate.query(dataSqlTable1, rowMapper, startTime);
			List<P2pIp> resultTable2 = jdbcTemplate.query(dataSqlTable2, rowMapper, endTime);

			resultTable1.addAll(resultTable2);
			result = resultTable1;

		}

		return result;
	}
}
